/*
* @Author: ywl
* @Last Modified by: ywl
* Description:
1.列表展示组件
2.slot: headerLeft =>表格顶部左侧信息;controlsBtn => 为表格列表操作列插槽
3.dicType: 列表配置动态字典类型值
4.dicProp: 列表配置动态字典的枚举字段
5.filter: 列表配置固定枚举对象
6.colOptionEnum: 动态枚举字典选项集合
7.handlerClick: 列表表格内点击事件
8.isSelection: 是否展示列表多选框 默认true
9.isClearSelection: 是否在列表数据刷新时清除勾选状态 默认true
10.isMarClass: 是否展示列表顶部信息或者按钮
11.isShowTooltip: 是否在鼠标悬浮时展示信息
*/
<template>
  <div class="myTable" style="width: 100%;height: 100%">
    <el-table
      ref="tableRef"
      style="width: 100%;"
      :data="tableData"
      size="small"
      :current-row-key="id"
      :row-key="getRowKeys"
      :empty-text="emptyText"
      row-class-name="row"
      cell-class-name="column"
      tooltip-effect="dark"
      :highlight-current-row="true"
      fit
      border
      @selection-change="handleSelectionChange"
      @cell-click="handlerClick"
      show-summary
      :summary-method="getSummaries"
    >
      <!--这是是为了将表格设置成带有选择框的表格-->
      <el-table-column v-if="isSelection" type="selection" :reserve-selection="true" align="center" width="45" />
      <el-table-column align="center" type="index" label="序号" width="50" />
      <el-table-column
        v-for="(item, index) in columns"
        :key="index"
        align="center"
        :prop="item.prop"
        :width="item.width"
        :label="item.label"
      >
        <template slot-scope="scope">
          <div
            v-if="item.isSelect && (scope.row.showSelect || +scope.row.addType === 1 || item.prop === 'supplierUserName') && types === 'todo'"
          >
            <!-- 下拉框选择 -->
            <el-select
              v-model="scope.row[item.dicProp.label]"
              placeholder="请选择"
              allow-create
              @change="handleOnEvent(item.prop, scope.row, scope.row[item.dicProp.label], item.selectType)"
              @focus="getDatalist(scope.row, item.prop, item.selectType)"
            >
              <el-option
                v-for=" (optionSelectItem, index) in selectList[item.selectType]"
                :key="index"
                :style="{ 'width': minWidth + 'px' }"
                :label="optionSelectItem[item.dicProp.label]"
                :value="optionSelectItem[item.dicProp.value]"
                @click.native="onlySelectControcde(item.prop, scope.row, scope.row[item.dicProp.label], item.selectType)"
              />
            </el-select>
          </div>
          <!-- 输入框/查看内容 -->
          <div v-else>
            <el-input
              v-if="item.isEdit && types === 'todo'"
              ref="tableInput"
              v-model="scope.row[item.prop]"
              class="pms-wz-input el-table-inline"
              size="mini"
              @mouseleave.native="handleMouseleave"
              @blur="removeClass()"
              @change="changeInput(item.prop, scope.$index, scope.row)"
            />
            <el-tooltip v-else :content="scope.row[item.prop] + ''">
              <span
                :style="{ cursor: item.prop === 'prjName' && (!noEdit||types==='done') ? 'pointer' : '', color: item.prop === 'prjName' && (!noEdit||types==='done') ? 'rgb(2,167,240)' : '' }"
                class="header-tooltip"
                @click="jumPage(scope.row, item.prop)"
              >{{ scope.row[item.prop]
              }}</span>
            </el-tooltip>
          </div>

        </template>
      </el-table-column>
      <slot name="controlsBtn" />
    </el-table>
  </div>
</template>

<script>
const regex = {
    // 不能输入中文、不能输入特殊字符、不能输入英文
    'first': /^-?\d+(\.\d+)?$/,
    // 不能输入特殊字符
    'second': /^[A-Za-z0-9\u4e00-\u9fa5_]+$/,
    'three': /^(?!0\d)\d*(?:\.\d{1,2})?$/,
    'four': /^-?\d+(\.\d{0,4})?$/
}
import store from '@/store'
import {
    isAllowEdits
} from '@/api/electSingnare/index'
export default {
    name: 'MyTable',
    // 因为是子组件，要接受父组件传递的数据，所以这里我们定义props
    props: {
        // 返回数据id
        id: {
            type: [String, Number],
            required: true,
            default: ''
        },
        // 父组件传递过来的表格数据
        tableData: {
            type: Array,
            default: () => []
        },
        // 父组件传递过来的表头数据
        columns: {
            type: Array,
            default: () => []
        },
        // 父组件传递过来的操作按钮数据
        tableOperation: {
            type: Array,
            default: () => []
        },
        // 列表数据枚举字段选项集
        colOptionEnum: {
            type: Object,
            default: () => ({})
        },
        isSelection: {
            type: Boolean,
            default: true
        },
        isMarClass: {
            type: Boolean,
            default: false
        },
        isClearSelection: {
            type: Boolean,
            default: true
        },
        emptyText: {
            type: String,
            default: '暂无数据'
        },
        // 下拉框的字典数据
        selectList: {
            type: Object,
            default: () => ({})
        },
        noEdit: {
            type: Boolean,
            default: false
        },
        taskInfoObj: {
            type: Object,
            default: () => ({})
        },
        types: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            eventName: 'click', // 点击按钮绑定的方法，这样写法也可以去绑定一些其他的比如change等方法
            multipleSelection: [], // 这个数组用来保存被选择行的数据，顺序是按照你勾选的顺序来排序的
            temporary: '',
            minWidth: 181
        }
    },
    watch: {
        tableData: {
            handler(newVal) {
                if (newVal.length && this.isClearSelection) {
                    this.$refs.tableRef.clearSelection()
                }
            },
            deep: true
        }
    },
    methods: {
        getSummaries(param) {
            const showContent = ['price','scoreMonth1','scoreMonth2','scoreMonth3','avgScore','taxPrice','prjCode','prjName','systemName', 'supplierCode','supplierName','supplierUserName','contractCode','creationDate']
            const { columns, data } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (index === 0) {
                    sums[index] = '合计';
                    return;
                }
                const values = data.map(item => {
                    return showContent.includes(column.property) ? NaN : Number(item[column.property])
                });
                if (!values.some(value => isNaN(value))) {
                    sums[index] = values.reduce((prev, curr) => {
                        const value = Number(curr);
                        if (!isNaN(value)) {
                            return prev + curr;
                        } else {
                            return prev;
                        }
                    }, 0);
                    sums[index] = Number(sums[index].toFixed(2));
                } else {
                    sums[index] = '';
                }
            });
            return sums;
        },
        // @selection-change方法可以监听到表格里哪一行被选中，类型是数组;
        // 然后我们将它赋值给定义好的 multipleSelection
        handleSelectionChange(rowList) {
            this.multipleSelection = rowList
            this.$emit('handleSelection', rowList)
            store.commit('settings/setTableCheckData', rowList)
        },
        // 数据id
        getRowKeys(row) {
            return row[this.id]
        },
        // 用于多选表格，切换某一行的选中状态
        toggleRowEvent(row, flag) {
            if (Array.isArray(row)) {
                row.forEach(item => {
                    this.$refs.tableRef.toggleRowSelection(item, flag)
                })
            } else {
                this.$refs.tableRef.toggleRowSelection(row, flag)
            }
        },
        // 清空选中
        clearSelection() {
            this.$refs.tableRef.clearSelection()
        },
        // 用于多选表格，切换所有行的选中状态
        toggleAllSelection() {
            this.$refs.tableRef.toggleAllSelection()
        },
        // 列表表格点击事件
        handlerClick(row, prop, cell) {
            // 暂存点击某一行的值
            this.temporary = row[prop.property]
            this.getClassName(cell)
            this.$emit('rowClick', row, prop)
        },
        //  鼠标离开单元格移除类名
        removeClass() {
            document.getElementsByClassName('current-cell')[0]?.classList.remove('current-cell')
        },
        // 动态获取类名样式 是否让编辑框显示
        getClassName(cell) {
            for (let i = 0; i < document.getElementsByClassName('current-cell').length; i++) {
                document.getElementsByClassName('current-cell')[i]?.classList.remove('current-cell')
            }
            cell?.classList.add('current-cell')
        },
        /**
         *
         * @param {*} item 表头字段
         * @param {*} index 下标
         * @param {*} row 表格行数据
         */
        async changeInput(item, index, row) {
            const allowChinese = ['systemName']
            // 不允许输入中文特殊字符
            const Bancharacter = !regex['first'].test(row[item])
            // 允许输入中文但不允许输入特殊字符
            const BancharacterTwo = !regex['second'].test(row[item])
            const { code, message } = await this.checkEditing(row)
            if (+code !== 200) {
                row[item] = this.temporary ? this.temporary : ''
                return this.$message({
                    message: message,
                    type: 'error',
                    dangerouslyUseHTMLString: true
                })
            }
            // 清空让他清呗
            if (row[item] === '') {
                this.$emit('changeInput', item, index, row)
                return
            }
            // 非法字符中英文限制特殊字符限制
            if (!allowChinese.includes(item) && Bancharacter || BancharacterTwo && allowChinese.includes(item)) {
                row[item] = this.temporary ? this.temporary : ''
                this.messageTitle()
                return
            } else {
                row[item] = this.processingAccuracy(item, row[item])
                // 计算平均成绩
                this.calcAverage(item, row)

                this.$emit('changeInput', item, index, row)
            }
        },
        async checkEditing(row) {
            if (!row.summaryId) {
                return {
                    code: 200,
                    message: '成功'
                }
            }
            const { taskId, taskYear, taskQuarter } = this.taskInfoObj
            const params = {
                taskId,
                taskYear,
                taskQuarter,
                summaryId: row.summaryId
                // prjCode: row.prjCode,
                // supplierCode: row.supplierCode,
                // contractCode: row.contractCode
            }
            const { code, message } = await isAllowEdits(params)
            return {
                code, message
            }
        },
        calcAverage(item, row) {
            // 平均成绩
            if (['scoreMonth1', 'scoreMonth2', 'scoreMonth3'].includes(item)) {
                const sumToatl = this.$add((Number(row['scoreMonth1']) + Number(row['scoreMonth2']) + Number(row['scoreMonth3'])))
                row['avgScore'] = this.$divide(Number(sumToatl), 3).toFixed(2)
            }
            if (['totalTaxAmount', 'taxDeducAmount'].includes(item)) {
                row['paymentTotalTaxAmount'] = (Number(+row['totalTaxAmount'] - Math.abs(Number(+row['taxDeducAmount'])))).toFixed(2)
            }
            if (['totalAmount', 'deducAmount'].includes(item)) {
                row['paymentTotalAmount'] = (Number(+row['totalAmount']) - Math.abs(Number(+row['deducAmount']))).toFixed(2)
            }
        },
        // 处理精度问题
        processingAccuracy(prop, item) {
            const backInfo = isNaN(item) ? item : Number(item).toString()
            const decimal4 = ['workLoads', 'taxPrice', 'price']
            const decimal2 = ['taxDeducAmount', 'deducAmount', 'totalAmount', 'totalTaxAmount', 'scoreMonth1', 'scoreMonth2', 'scoreMonth3']
            if (decimal4.includes(prop)) {
                return Number(backInfo).toFixed(4)
            } else if (decimal2.includes(prop)) {
                return Number(backInfo).toFixed(2)
            } else {
                return backInfo
            }
        },
        messageTitle(message = '非法字符！') {
            this.$message({
                message: message,
                type: 'warning'
            })
        },
        // 下拉框选择数据
        async handleOnEvent(item, row, label, types) {
            if (['prjCode', 'prjName', 'supplierCode', 'supplierName'].includes(item)) {
                const clearValue = ['prjCode', 'prjName'].includes(item) ? ['supplierCode', 'supplierName', 'supplierUserName', 'contractCode'] : ['supplierUserName', 'contractCode']
                for (let i = 0; i < clearValue.length; i++) {
                    row[clearValue[i]] = ''
                }
            }
            const { code, message } = await this.checkEditing(row)
            if (+code !== 200) {
                this.$message({
                    message: message,
                    type: 'error',
                    dangerouslyUseHTMLString: true
                })
                this.$emit('refrshDosearch')
                return
            }
            this.$emit('selectChangeFun', item, row, label, types)
        },
        // 暂时不用
        async onlySelectControcde(item, row, label, types) {
            console.log('todo')
        },
        getDatalist(row, item, selectType) {
            if (item === 'prjCode' || item === 'prjName') {
                return
            }
            this.$emit('foucsChange', row, item, selectType)
        },
        jumPage(row, item) {
            if ((!this.noEdit || this.types === 'done') && item === 'prjName') {
                console.log(row, '跳转页面')
                const url = `${process.env.VUE_APP_JUNNAN_IFRAME_URL}prjQueryAndExport/projectBaseInfo?prjId=${row['prjId']}`
                window.open(url, '_blank')
            }
        },
        handleMouseleave() {
            this.$nextTick(() => {
                for (let i = 0; i < this.$refs.tableInput.length; i++) {
                    this.$refs?.tableInput[i]?.blur()
                }
            })
        }
    }
}
</script>

<style lang="scss" scoped>
::v-deep .el-input__inner {
    height: 24px !important;
    font-size: 12px !important;
    box-sizing: border-box;
    width: 100%;
    text-align: center !important;
}

::v-deep .el-table__row td .el-select .el-input--suffix .el-input__suffix {
    top: 7px;
}

::v-deep .el-table__row td .el-select .is-focus .el-input__suffix {
    top: -8px;
}

::v-deep .pms-button-primary {
    color: #fff;
}

.header-tooltip {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
    padding: 0 5px
}

::v-deep .el-table__empty-block {
    width: 100%;
    min-width: 100%;
    max-width: 100%;
}

::v-deep .el-table .cell {
    padding-left: 0;
    padding-right: 0;
}
</style>
